package com.fingard.xml;

import java.util.ArrayList;
import java.util.Stack;

import com.fingard.text.StringHelper;
import com.fingard.text.XmlHelper;

public class XmlTextWriter {
	
	private StringBuilder sbXml = null;
	//private ArrayList<String> listStartTag = null;
	
	private Stack<String> stackStartTag = null;
	
	public XmlTextWriter(){
		sbXml = new StringBuilder();
		stackStartTag = new Stack<String>();
	}
	public boolean autoFormat = true;

	public void writeStartDocument(){
		
	}
	
	public void directWrite(String p_xml){
		sbXml.append(p_xml);
	}
	
	public void writeStartDocByDeclaration(String value){
		if(autoFormat){
			sbXml.append(value+"\r\n");
		}
		else{
			sbXml.append(value);
		}
	}

	
	public void writeEndDocument(){
		int tmpOldSize = stackStartTag.size();
		if(tmpOldSize > 0){
			for(int idx=0;idx<tmpOldSize;idx++){
				writeEndElement();
			}
		}
	}
	
	public void writeXElement(XElement p_XElement){
		if(p_XElement.sizeSubNode() > 0){
			String nameAndAttr = p_XElement.getNameAttrForWrite();
			if(StringHelper.hasAnyChar(nameAndAttr)){
				writeStartElementByAttr(p_XElement.name, nameAndAttr);	
			}else{
				writeStartElement(p_XElement.name);	
			}
			if(!StringHelper.isNullOrEmpty(p_XElement.innerText)){
				sbXml.append(XmlHelper.encode(p_XElement.innerText));
				isLastWriteElmnt = false;
			}
			ArrayList<XElement> tmpList = p_XElement.getAllChildList();
			for(int i=0;i<tmpList.size();i++){
				writeXElement(tmpList.get(i));
			}
			writeEndElement();
		}
		else{
			writeFormatString();
			sbXml.append("<" + p_XElement.name);
			String attrStr = p_XElement.getOnlyAttrForWrite();
			if(StringHelper.hasAnyChar(attrStr)){
				sbXml.append(attrStr);
			}
			if(StringHelper.isNullOrEmpty(p_XElement.innerText)){
				if(p_XElement.isSelfClosed){
					sbXml.append("/>");
				}else{
					sbXml.append("></"+p_XElement.name+">");
				}
			}else{
				sbXml.append(">");
				sbXml.append(XmlHelper.encode(p_XElement.innerText));
				sbXml.append("</"+p_XElement.name+">");
			}
			isLastWriteElmnt = true;
		}
	}
	//不做特殊字符转义
	public void writeXElementWithoutTransfer(XElement p_XElement){
		if(p_XElement.sizeSubNode() > 0){
			String nameAndAttr = p_XElement.getNameAttrForWrite();
			if(StringHelper.hasAnyChar(nameAndAttr)){
				writeStartElementByAttr(p_XElement.name, nameAndAttr);
			}else{
				writeStartElement(p_XElement.name);
			}
			if(!StringHelper.isNullOrEmpty(p_XElement.innerText)){
				sbXml.append(p_XElement.innerText);
				isLastWriteElmnt = false;
			}
			ArrayList<XElement> tmpList = p_XElement.getAllChildList();
			for(int i=0;i<tmpList.size();i++){
				writeXElementWithoutTransfer(tmpList.get(i));
			}
			writeEndElement();
		}
		else{
			writeElementStringWithoutTransfer(p_XElement.name, p_XElement.innerText, true);
		}
	}
	private boolean isLastWriteElmnt = false;//是否紧挨着结束节点，用于格式化判断
	
	public void writeStartElement(String p_localName){
		writeFormatString();
		stackStartTag.push(p_localName);
		sbXml.append("<" + p_localName + ">");
		isLastWriteElmnt = true;
	}
	
	public void writeStartElementByAttr(String p_localName, String p_startByAttr){
		writeFormatString();
		stackStartTag.push(p_localName);
		sbXml.append(p_startByAttr);
		isLastWriteElmnt = true;
	}
	
	public void writeEndElement(){
		String tmpLocalName = stackStartTag.pop();
		writeFormatString();
		sbXml.append("</" + tmpLocalName + ">");
		isLastWriteElmnt = true;
	}
	
	public void writeElementClosed(String p_localName){//Symmetry对称关闭
		writeFormatString();
		sbXml.append("<" + p_localName + "></" + p_localName + ">");
		isLastWriteElmnt = true;
	}
	
	public void writeElementString(String p_localName, String p_value){
		writeElementString(p_localName.trim(), p_value, false);
	}

    public void writeElementStringWithoutTransfer(String p_localName, String p_value){
        writeElementStringWithoutTransfer(p_localName.trim(), p_value, false);
    }
	
	//p_symmetryClosed如果字符为空，是否对称关闭
	public void writeElementString(String p_localName, String p_value, boolean p_symmetryClosed){
		writeFormatString();
		if(p_value == null || p_value.length() == 0){
			if(p_symmetryClosed){
				sbXml.append("<" + p_localName + "></" + p_localName + ">");
			}
			else{
				sbXml.append("<" + p_localName + "/>");
			}
		}
		else{
			sbXml.append("<" + p_localName + ">" + XmlHelper.encode(p_value) + "</" + p_localName + ">");
		}
		isLastWriteElmnt = true;
	}
	//不进行字符串转义
	public void writeElementStringWithoutTransfer(String p_localName, String p_value, boolean p_symmetryClosed){
		writeFormatString();
		if(p_value == null || p_value.length() == 0){
			if(p_symmetryClosed){
				sbXml.append("<" + p_localName + "></" + p_localName + ">");
			}
			else{
				sbXml.append("<" + p_localName + "/>");
			}
		}
		else{
			sbXml.append("<" + p_localName + ">" + p_value + "</" + p_localName + ">");
		}
		isLastWriteElmnt = true;
	}

	
	public void writeElementCDATA(String p_localName, String p_CDATA){
		writeFormatString();
		if(p_CDATA == null || p_CDATA.length() == 0){
			sbXml.append("<" + p_localName + "><![CDATA[]]></" + p_localName + ">");
		}
		else{
			sbXml.append("<" + p_localName + "><![CDATA[" + p_CDATA + "]]></" + p_localName + ">");
		}
		isLastWriteElmnt = true;
	}
	
	private void writeFormatString(){
		if(isLastWriteElmnt && autoFormat){
			sbXml.append("\r\n");
			int tmpSize = stackStartTag.size();
			if(tmpSize > 0){
				for(int i=0;i<tmpSize;i++){
					sbXml.append("  ");
				}
			}
		}
	}
	
	/**输出xml字符串*/
	public String toXmlString(){
		return sbXml.toString();
	}
	
	public StringBuilder getSbXml(){
		return sbXml;
	}

    public void writeElementAttribute(String p_elementName,String p_elementValue,String p_attributeName,String p_attributeValue)
    {
        writeFormatString();
        if(p_elementValue == null || p_elementValue.length() == 0){
            sbXml.append("<" + p_elementName + "/>");
        }
        else{
            sbXml.append("<" + p_elementName +" " + p_attributeName + " = " + "\"" + p_attributeValue + "\"" + ">");
            sbXml.append( XmlHelper.encode(p_elementValue) + "</" + p_elementName + ">");
        }
    }

	public void writeElementAttribute(String p_elementName,String p_attributeName,String p_attributeValue)
	{
		writeFormatString();
		stackStartTag.push(p_elementName);
		sbXml.append("<" + p_elementName +" " + p_attributeName + " = " + "\"" + p_attributeValue + "\"" + ">");
		isLastWriteElmnt = true;
	}

	public void writeElementStringNotNull(String p_localName, String p_value){
		if(!(StringHelper.isNullOrEmpty(p_value) || p_value.length() == 0)) {
			writeElementString(p_localName, p_value, false);
		}
	}

//	获取标签内的内容
	public String getContentBetweenTag(String p_TagName){
		int Start = sbXml.indexOf("<"+p_TagName + ">") + p_TagName.length() + 2;	//加<TagName>的长度
		int End  = sbXml.lastIndexOf("</"+ p_TagName + ">");
		if(End < Start || End > sbXml.length()){
			return "";
		}
		String str =  sbXml.substring(Start,End);
		return str;
	}

//	将内容插入空白标签
	public void insertIntoTag(String p_TagName,String p_Data){
		if(sbXml.indexOf("<"+ p_TagName + ">") == -1 && sbXml.indexOf("<"+ p_TagName + "/>") == -1){
			return;
		}
		if(sbXml.indexOf("<"+ p_TagName + ">") != -1) {
			int Start = sbXml.indexOf("<" + p_TagName + ">") + p_TagName.length() + 2;    //加<TagName>的长度 未测
			int End   = sbXml.indexOf("</" + p_TagName +">");
			sbXml.replace(Start,End,p_Data);
		}
		else if(sbXml.indexOf("<"+ p_TagName + "/>")  != -1){	//<Sign />这种形式可用
			int Start = sbXml.indexOf("<" + p_TagName);
			String Endstr = "<"+ p_TagName + "/>";
			int End   = sbXml.indexOf("<" + p_TagName) + Endstr.length();
			String finalData = "<"+p_TagName+">" + p_Data + "</" + p_TagName + ">";
			sbXml.replace(Start,End,finalData);
		}
	}
}
